package com.hup.vd.view.taskCluster;

import com.hup.utils.commons.TextUtil;
import com.hup.utils.commons.exception.AppCommonException;
import com.hup.utils.commons.hardware.MouseUtil;
import com.hup.utils.commons.start.DialogHelper;
import com.hup.utils.commons.start.SpringContext;
import com.hup.utils.commons.thread.ThreadUtil;
import com.hup.utils.swing.customView.BaseFileChooser.FixedJFileChooser;
import com.hup.utils.swing.customView.BaseUndoText;
import com.hup.utils.swing.frame.BaseDialog;
import com.hup.utils.swing.frame.SingletonWindowHelper;
import com.hup.vd.model.bo.TaskCreateReq;
import com.hup.vd.model.config.AppConfig;
import com.hup.vd.model.config.TaskInfo;
import com.hup.vd.service.TaskService;
import com.hup.vd.view.MainFrame;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.springframework.util.StringUtils;

import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.filechooser.FileSystemView;
import javax.swing.undo.UndoManager;
import java.awt.Dimension;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.util.ArrayList;
import java.util.Objects;

/**
 * 批量创建任务弹窗
 *
 * @author hugan
 * @date 2022/8/10
 */
@Slf4j
public class TaskClusterDialog extends BaseDialog {

    private final AppConfig config;
    private TaskClusterForm form;

    private final String initFile;
    private final int initNumSt;
    private final String initUrl;

    public static void doShow() {
        TaskClusterDialog window = SingletonWindowHelper.getWindow(TaskClusterDialog.class);
        if (window == null) {
            log.info("创建弹窗");
            window = new TaskClusterDialog();
        } else {
            log.info("复用弹窗");
        }
        JFrame parent = SingletonWindowHelper.getWindow(MainFrame.class);
        window.setAlwaysOnTop(parent.isAlwaysOnTop());
        window.setVisible(true);
        window.toFront();
    }

    private TaskClusterDialog() {
        super("批量创建任务");
        setModal(false);
        config = SpringContext.getBean(AppConfig.class);
        initView();
        initListener();

        form.txtFilePath.setText(config.getClusterFilePath() != null ? config.getClusterFilePath() : config.getLastSavePath());//要放在initUndo后面,否则text变空,未深究bug
        if (config.getClusterNumSt() != null) form.txtNumSt.setIntValue(config.getClusterNumSt());
        form.txtUrls.setText(config.getLastUrl());
        initFile = form.txtFilePath.getText();
        initNumSt = form.txtNumSt.getIntValue();
        initUrl = form.txtUrls.getText();
    }

    private void initView() {
        form = new TaskClusterForm();
        setContentPane(form.root);

        JFrame parent = SingletonWindowHelper.getWindow(MainFrame.class);
        Dimension size = parent.getSize();
        size.width -= 100;
        size.height -= 100;
        setSize(size);
        setLocationRelativeTo(parent);
        setAlwaysOnTop(parent.isAlwaysOnTop());
    }

    private void initListener() {
        setEscapeCancelable(true);
        BaseUndoText.initUndo(form.txtFilePath, new UndoManager());
        BaseUndoText.initUndo(form.txtUrls, new UndoManager());
        form.txtFilePath.addMouseListener(new MouseAdapter() {
            @SuppressWarnings("DuplicatedCode")
            @Override
            public void mouseClicked(MouseEvent e) {
                if (e.getClickCount() != 2 || !MouseUtil.isLeftButton(e)) return;

                //设置初始目录
                File initDir = null;
                String oldFileName = null;
                String filePath = form.txtFilePath.getText();
                if (!TextUtil.isBlank(filePath)) {
                    File file = new File(filePath);
                    if (!file.isDirectory()) {
                        oldFileName = file.getName();
                        file = file.getParentFile();
                    }
                    if (file != null && file.exists()) initDir = file;
                }
                //省缺为桌面
                if (initDir == null) initDir = FileSystemView.getFileSystemView().getHomeDirectory();

                //打开文件选择器
                FixedJFileChooser fc = new FixedJFileChooser(null);
                fc.setCurrentDirectory(initDir);
                fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
                fc.setDialogTitle("保存路径");
                fc.setFileName(oldFileName);
                fc.showDialog(TaskClusterDialog.this, "确定");//标题,提交按钮的字
                //处理结果
                File selectedFile = fc.getSelectedFile();
                if (selectedFile != null) {
                    form.txtFilePath.setText(selectedFile.getAbsolutePath());
                }
            }
        });
        form.btnOk.addActionListener(e -> doInBackground(getTitle(), () -> {
            String filePath = form.txtFilePath.getText();
            String ext = FilenameUtils.getExtension(filePath).toLowerCase();//转小写
            if (!filePath.endsWith(ext)) {
                //log.info("filePath={}, {}", filePath, ext);
                filePath = filePath.substring(0, filePath.length() - ext.length()) + ext;
                form.txtFilePath.setText(filePath);
            }

            int num = form.txtNumSt.getIntValue();
            config.setClusterFilePath(filePath);
            config.setClusterNumSt(num);
            config.save();

            //校验
            if (!StringUtils.hasText(filePath)) throw new AppCommonException("请输入[路径]");
            if (!filePath.contains("#")) throw new AppCommonException("[路径]中缺少符号: #");
            String urlsText = form.txtUrls.getText();
            if (!StringUtils.hasText(urlsText)) throw new AppCommonException("请输入[地址]");

            //预览文本
            filePath = filePath.replaceFirst("#", "%d");
            String[] urls = urlsText.split("\n");
            int count = 0;//任务数量
            for (String url : urls) if (StringUtils.hasText(url)) count++;
            /*
            在顶部插入n个空格,解决Dialog.scrollView中文字宽度计算偏小的问题
            最后一行的字数(偏大的)=url+路径+ 数量的位数 + [/t等字符]
             */
            int maxCharCount = urls[urls.length - 1].length() + filePath.length() + ((int) Math.log10(count) + 1) + 10;
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < maxCharCount; i++) sb.append(" ");
            //真正有用的内容
            sb.append("\n确定创建任务? \t数量=").append(count).append('\n');
            for (String url : urls) {
                if (!StringUtils.hasText(url)) continue;
                sb.append(url).append("\t").append(String.format(filePath, num)).append("\n");
                num++;
            }
            //预览弹窗
            DialogHelper.yesNo(sb.toString()).okAction(() -> doInBackground(getTitle(), () ->
                    doCreateTask(urls))
            ).show(this);
        }));
        form.btnCancel.addActionListener(e -> onCancel());
    }

    /**
     * 逐个创建任务
     */
    private void doCreateTask(String[] urls) {
        log.info("开始批量创建任务, size<={}", urls.length);
        TaskService taskService = SpringContext.getBean(TaskService.class);
        String filePath = form.txtFilePath.getText().trim().replaceFirst("#", "%d");
        int num = form.txtNumSt.getIntValue();
        ArrayList<TaskInfo> taskInfos = new ArrayList<>();
        try {
            for (String url : urls) {
                if (!StringUtils.hasText(url)) continue;
                TaskCreateReq req = new TaskCreateReq();
                req.setUrl(url);
                req.setFilePath(String.format(filePath, num));
                req.setStartNow(true);

                //创建任务
                TaskInfo task = taskService.createTask(req);
                taskInfos.add(task);
                num++;
                ThreadUtil.sleep(10);

                config.setLastUrl(url);
                config.setLastSavePath(req.getFilePath());
            }
            dispose();
        } finally {
            if (!taskInfos.isEmpty()) {
                config.save();
                MainFrame mainFrame = SingletonWindowHelper.getWindow(MainFrame.class);
                mainFrame.afterCreateTasks(taskInfos);
            }
        }
    }

    @Override
    public void onCancel() {
        boolean changed = !Objects.equals(form.txtFilePath.getText(), initFile)
                || form.txtNumSt.getIntValue() != initNumSt
                || !Objects.equals(form.txtUrls.getText(), initUrl);
        if (!changed) {
            dispose();
            return;
        }
        DialogHelper.yesNo("确定退出?").okAction(this::dispose).show(this);
    }

}
